﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using JT808.Gateway.Abstractions;
using JT808.Gateway.Abstractions.Dtos;
using JT808.Gateway.QueueServer.Custom.Dtos;
using JT808.Gateway.Services;
using JT808.Gateway.Session;
using JT808.Protocol;
using JT808.Protocol.Enums;
using JT808.Protocol.Extensions;
using JT808.Protocol.Extensions.JT1078.MessageBody;
using JT808.Protocol.MessageBody;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Polly.Caching;

namespace JT808.Gateway.QueueServer.Custom
{
    /// <summary>
    /// jt808 webapi
    /// </summary>
    [ApiController]
    [Route("jt808api")]
    public sealed class JT808WebApiExt : ControllerBase
    {
        /// <summary>
        /// 
        /// </summary>
        JT808SessionManager SessionManager;
        /// <summary>
        /// 
        /// </summary>
        JT808BlacklistManager BlacklistManager;
        IJT808Config JT808Config;
        JT808Serializer JT808Serializer { get; }

        IJT808WebApiService WebApiService { get; }
        ILogger Logger { get; }

        public JT808WebApiExt(
            JT808SessionManager jT808SessionManager,
            JT808BlacklistManager jT808BlacklistManager,
            IJT808Config jT808Config, IJT808WebApiService apiService,
            ILoggerFactory loggerFactory)
        {
            this.SessionManager = jT808SessionManager;
            this.BlacklistManager = jT808BlacklistManager;
            this.JT808Config = jT808Config;
            this.JT808Serializer = jT808Config.GetSerializer();
            WebApiService = apiService;
            Logger = loggerFactory.CreateLogger<JT808WebApiExt>();
        }

        /// <summary>
        /// index
        /// </summary>
        /// <returns></returns>
        [HttpGet("index")]
        public ActionResult<JT808ResultDto<string>> Index()
        {
            JT808ResultDto<string> resultDto = new JT808ResultDto<string>();
            resultDto.Data = "Hello,JT808 WebApi";
            resultDto.Code = JT808ApiResultCode.Ok;
            return resultDto;
        }

        /// <summary>
        /// 统一下发设备消息服务
        /// </summary>
        /// <returns></returns>
        [HttpPost("unification-send")]
        public async Task<ActionResult<JT808ResultDto<bool>>> UnificationSend([FromBody] JT808UnificationSendRequestDto parameter)
        {
            JT808ResultDto<bool> resultDto = new();
            try
            {
                resultDto.Data = await SessionManager.TrySendByTerminalPhoneNoAsync(parameter.TerminalPhoneNo, Convert.FromHexString(parameter.HexData));
                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Data = false;
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 根据订阅id查询响应状态，0：未响应 1：已响应 2：已超时 3：未订阅或已失效
        /// </summary>
        /// <param name="subscribeId"></param>
        /// <returns></returns>
        [HttpGet("task/{subscribeId}")]
        public ActionResult<JT808ResultDto<ushort>> TaskStatus(string subscribeId)
        {
            JT808ResultDto<ushort> resultDto = new();
            try
            {
                if (WebApiService.SubscribeIds.TryGetValue(subscribeId, out var status))
                {
                    resultDto.Data = status;
                }
                else
                {
                    resultDto.Data = 3; // 未订阅或已失效
                }
                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Message = ex.Message;
                resultDto.Code = JT808ApiResultCode.Error;
            }

            return resultDto;
        }

        private async Task<ActionResult<JT808ResultDto<Object>>> SendAndSubscribe(string sim, JT808Package package, string callback)
        {
            JT808ResultDto<Object> resultDto = new();
            var (online, id) = await WebApiService.TrySendIfOnline(package, callback);
            if (online)
            {
                Logger.LogInformation("Successfully send message and subscribe its response");
                var data = new
                {
                    subscribeId = id,
                    useCallback = callback != null
                };
                resultDto.Data = data;
                resultDto.Code = JT808ApiResultCode.Ok;
                return Accepted($"/jt808api/task/{id}", resultDto);
            }
            else
            {
                var msg = $"[终端卡号：{sim}]：终端不在线";
                resultDto.Message = msg;
                resultDto.Code = JT808ApiResultCode.DeviceNotFound;
                return Ok(resultDto);
            }
        }

        [HttpGet("terminal/property")]
        public async Task<ActionResult<JT808ResultDto<Object>>> QueryTerminalProperty([FromQuery] string sim, [FromQuery] bool VersionFlag = false)
        {
            JT808ResultDto<Object> resultDto = new();
            try
            {
                JT808Package queryPackage;
                if (VersionFlag)
                    queryPackage = JT808MsgId._0x8107.Create2019(sim, new JT808_0x8107());
                else
                    queryPackage = JT808MsgId._0x8107.Create(sim, new JT808_0x8107());
                var version = VersionFlag ? JT808Version.JTT2019 : JT808Version.JTT2013;
                var response = await SessionManager.TrySendPackageAndWaitAsync(sim, queryPackage, JT808Serializer, version);
                if (response == null)
                    resultDto.Message = $"[终端卡号：{sim}]：终端不在线";
                else
                    resultDto.Data = response.Bodies as JT808_0x0107;
                return Ok(resultDto);
            }
            catch (Exception ex)
            {
                resultDto.Message = ex.Message;
                resultDto.Code = JT808ApiResultCode.Error;
                return StatusCode(500, resultDto);
            }
        }

        //[HttpGet("terminals/{sim}/settings")]
        //public async Task<ActionResult<JT808ResultDto<Object>>> QueryTerminalSettings([FromRoute] string sim, [FromQuery] string callback)
        //{
        //    JT808ResultDto<Object> resultDto = new();
        //    try
        //    {

        //    }
        //}

        #region 业务端连接模拟测试
        [HttpGet("terminal-property")]
        public async Task<ActionResult<JT808ResultDto<Dictionary<string, Object>>>> QueryTerminalPropertyBusiness([FromQuery] string sim, [FromQuery] string callback)
        {
            JT808ResultDto<Dictionary<string, Object>> resultDto = new();
            try
            {
                HttpClient client = new HttpClient();
                if (Uri.TryCreate($"http://127.0.0.1:1808/jt808api/terminals/{sim}/property?callback={callback}", UriKind.Absolute, out var url))
                {
                    var response = await client.GetAsync(url);
                    response.EnsureSuccessStatusCode();
                    // 读取响应内容
                    string responseBody = await response.Content.ReadAsStringAsync();
                    if (responseBody == null)
                    {
                        Logger.LogError($"response of [{url}] is null!");
                        resultDto.Code = JT808ApiResultCode.Error;
                        resultDto.Message = $"response of [{url}] is null!";
                        return StatusCode(500, resultDto);
                    }
                    var doc = JsonDocument.Parse(responseBody);
                    var json = doc.RootElement;
                    if (json.GetProperty("data").ValueKind != JsonValueKind.Null && json.GetProperty("data").TryGetProperty("subscribeId", out var key))
                    {
                        var res = await TryTakeFromDictionaryAsync(WebApiService.CachedResponse, key.GetString(), 1000);
                        if (res.Success)
                        {
                            var j = JsonSerializer.Deserialize<Dictionary<string, Object>>(res.Output);
                            resultDto.Data = j;
                        }
                    }
                    else if (json.TryGetProperty("code", out var codeElement) &&
                        codeElement.GetInt16() == JT808ApiResultCode.DeviceNotFound)
                    {
                        resultDto.Code = JT808ApiResultCode.DeviceNotFound;
                        resultDto.Data = json.GetProperty("data").Deserialize<Dictionary<string, Object>>();
                        resultDto.Message = json.GetProperty("message").Deserialize<string>();
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError(ex.Message, ex);
                Logger.LogError(ex.StackTrace, ex);
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        [HttpPost("callback-test/{subscribeId}")]
        public async Task<ActionResult<JT808ResultDto<Object>>> CallbackTest(string subscribeId)
        {
            JT808ResultDto<Object> resultDto = new();

            try
            {
                // 读取请求体
                using (StreamReader reader = new(Request.Body, Encoding.UTF8))
                {
                    string body = await reader.ReadToEndAsync(); // 获取请求体内容
                    Logger.LogInformation($"Callback from id={subscribeId}");
                    Logger.LogInformation($"body is {body}");
                    resultDto.Data = true;
                    resultDto.Code = JT808ApiResultCode.Ok;
                }
            }
            catch (Exception ex)
            {
                resultDto.Message = ex.Message;
                resultDto.Code = JT808ApiResultCode.Error;
            }

            return resultDto;
        }
        #endregion

        [HttpPost("video/load")]
        public async Task<ActionResult<JT808ResultDto<string>>> RealTimeVideoTransferStart(
            [FromQuery] string sim, [FromBody] JT808VideoTransferRequestDto param, [FromQuery] bool VersionFlag = false)
        {
            var result = new JT808ResultDto<string>();
            try
            {
                string serverIp = "8.147.116.86";
                var request = new JT808Package
                {
                    Header = new JT808Header
                    {
                        MsgId = 0x9101,
                        TerminalPhoneNo = sim,
                        ProtocolVersion = (byte)(VersionFlag ? 1 : 0)
                    },
                    Bodies = new JT808_0x9101
                    {
                        ServerIp = serverIp,
                        TcpPort = 1078,
                        ChannelNo = param.LogicalChannelNo,
                        DataType = param.DataType,
                        StreamType = param.StreamType
                    }
                };
                request.Header.MessageBodyProperty.VersionFlag = VersionFlag;

                var version = VersionFlag ? JT808Version.JTT2019 : JT808Version.JTT2013;
                var response = await SessionManager.TrySendPackageAndWaitAsync(sim, request, JT808Serializer, version);
                if (response == null)
                    result.Message = $"[终端卡号：{sim}]：终端不在线";
                else
                {
                    var body = response.Bodies as JT808_0x0001;
                    result.Data = body.TerminalResult.GetName();
                }
                result.Code = JT808ApiResultCode.Ok;
                return result;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex.Message, ex);
                Logger.LogError(ex.StackTrace, ex);
                result.Message = ex.Message;
                result.Code = JT808ApiResultCode.Error;
                return result;
            }
        }

        [HttpPost("video/control")]
        public async Task<ActionResult<JT808ResultDto<string>>> RealTimeVideoTransferStop([FromQuery] string sim, [FromBody] VideoControlBodyDto control, [FromQuery] bool VersionFlag=false)
        {
            var result = new JT808ResultDto<string>();
            try
            {
                var request = new JT808Package
                {
                    Header = new JT808Header
                    {
                        MsgId = 0x9102,
                        TerminalPhoneNo = sim,
                    },
                    Bodies = new JT808_0x9102
                    {
                        ChannelNo = control.ChannelNo,
                        ControlCmd = control.Cmd,
                        CloseAVData = control.CloseType,
                        StreamType = control.StreamType,
                    }
                };
                request.Header.MessageBodyProperty.VersionFlag = VersionFlag;

                var version = VersionFlag ? JT808Version.JTT2019 : JT808Version.JTT2013;
                var response = await SessionManager.TrySendPackageAndWaitAsync(sim, request, JT808Serializer, version);
                if (response == null)
                    result.Message = $"[终端卡号：{sim}]：终端不在线";
                else
                {
                    var body = response.Bodies as JT808_0x0001;
                    result.Data = body.TerminalResult.GetName();
                }   
                result.Code = JT808ApiResultCode.Ok;
                return result;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex.Message, ex);
                Logger.LogError(ex.StackTrace, ex);
                result.Message = ex.Message;
                result.Code = JT808ApiResultCode.Error;
                return result;
            }
        }

        [HttpPost("video/list")]
        public async Task<ActionResult<JT808ResultDto<Object>>> QueryVideoResourceList([FromQuery] string sim, [FromBody] VideoListRequestDto condition, [FromQuery] bool VersionFlag = false)
        {
            JT808ResultDto<Object> result = new();
            try
            {
                var request = new JT808Package
                {
                    Header = new JT808Header
                    {
                        MsgId = 0x9205,
                        TerminalPhoneNo = sim,
                        ProtocolVersion = (byte)(VersionFlag ? 1 : 0)
                    },
                    Bodies = new JT808_0x9205
                    {
                        ChannelNo = condition.LogicalChannelNo,
                        BeginTime = DateTime.Parse(condition.StartTime),
                        EndTime = DateTime.Parse(condition.EndTime),
                        AlarmFlag = (ulong)condition.AlarmFlag,
                        MediaType = condition.DataType,
                        StreamType = condition.StreamType,
                        MemoryType = 0
                    }
                };
                request.Header.MessageBodyProperty.VersionFlag = VersionFlag;

                var version = VersionFlag ? JT808Version.JTT2019 : JT808Version.JTT2013;
                var response = await SessionManager.TrySendPackageAndWaitAsync(sim, request, JT808Serializer, version);
                if (response == null)
                    result.Message = $"[终端卡号：{sim}]：终端不在线";
                else
                    result.Data = response.Bodies as JT808_0x1205;
                return Ok(result);
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, ex.Message);
                Logger.LogError(ex.StackTrace, ex);
                result.Message = ex.Message;
                result.Code = 500;
                return StatusCode(500, result);
            }
        }

        [HttpGet("terminal/parameters")]
        public async Task<ActionResult<JT808ResultDto<Object>>> QueryTerminalParams([FromQuery] string sim, [FromQuery] bool VersionFlag)
        {
            JT808ResultDto<Object> resultDto = new();
            try
            {
                JT808Package queryPackage;
                if (VersionFlag)
                {
                    queryPackage = JT808MsgId._0x8104.Create2019(sim, new JT808_0x8104());
                }
                else
                {
                    queryPackage = JT808MsgId._0x8104.Create(sim, new JT808_0x8104());
                }
                var version = VersionFlag ? JT808Version.JTT2019 : JT808Version.JTT2013;
                var response = await SessionManager.TrySendPackageAndWaitAsync(sim, queryPackage, JT808Serializer, version);
                if (response == null)
                    resultDto.Message = $"[终端卡号：{sim}]：终端不在线";
                else
                    resultDto.Data = response.Bodies as JT808_0x0104;
                resultDto.Code = JT808ApiResultCode.Ok;
                return resultDto;
            }
            catch (Exception ex)
            {
                resultDto.Message = ex.Message;
                resultDto.Code = JT808ApiResultCode.Error;
                Logger.LogError(ex, ex.StackTrace);
                return StatusCode(500, resultDto);
            }
        }

        private JT808Package PositionQueryPackage(string sim, bool VersionFlag)
        {
            return new JT808Package
            {
                Header = new JT808Header
                {
                    MsgId = 0x8201,
                    TerminalPhoneNo = sim,
                    ProtocolVersion = (byte)(VersionFlag ? 1 : 0)
                },
                Bodies = new JT808_0x8201()
            };
        }

        private JT808Package PlateformCommonReply(string sim, bool VersionFlag)
        {
            return new JT808Package
            {
                Header = new JT808Header
                {
                    MsgId = 0x8001,
                    TerminalPhoneNo = sim,
                    ProtocolVersion = (byte)(VersionFlag ? 1 : 0)
                },
                Bodies = new JT808_0x8001()
            };
        }

        [HttpGet("terminal/isonline")]
        public async Task<ActionResult<JT808ResultDto<bool>>> CheckTerminalIsOnline([FromQuery] string sim, [FromQuery] bool VersionFlag = false)
        {
            JT808ResultDto<bool> result = new();
            try
            {
                var version = VersionFlag ? JT808Version.JTT2019 : JT808Version.JTT2013;
                var online = await SessionManager.TrySendPackageAsync(sim, PositionQueryPackage(sim, VersionFlag), JT808Serializer, version);
                result.Data = online;
                return result;
            }
            catch (Exception ex)
            {
                Logger.LogError(ex, ex.Message);
                Logger.LogError(ex, ex.StackTrace);
                result.Message = ex.Message;
                result.Code = JT808ApiResultCode.Error;
                return StatusCode(500, result);
            }
        }

        /// <summary>
        /// 会话服务-Tcp会话查询
        /// </summary>
        /// <returns></returns>
        [HttpGet("tcp/session/get-all")]
        public ActionResult<JT808ResultDto<List<JT808TcpSessionInfoDto>>> SessionTcpGetAll()
        {
            JT808ResultDto<List<JT808TcpSessionInfoDto>> resultDto = new JT808ResultDto<List<JT808TcpSessionInfoDto>>();
            try
            {
                resultDto.Data = SessionManager.GetTcpAll().Select(s => new JT808TcpSessionInfoDto
                {
                    LastActiveTime = s.ActiveTime,
                    StartTime = s.StartTime,
                    TerminalPhoneNo = s.TerminalPhoneNo,
                    RemoteAddressIP = s.RemoteEndPoint.ToString(),
                }).ToList();

                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Data = new List<JT808TcpSessionInfoDto>();
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 会话服务-Tcp分页会话查询
        /// jt808api/Tcp/Session/SessionTcpByPage?pageIndex=0&pageSize10
        /// </summary>
        /// <returns></returns>
        [HttpGet("tcp/session/session-tcp-by-page")]
        public ActionResult<JT808ResultDto<JT808PageResult<List<JT808TcpSessionInfoDto>>>> SessionTcpByPage([FromQuery] int pageIndex = 0, [FromQuery] int pageSize = 10)
        {
            JT808ResultDto<JT808PageResult<List<JT808TcpSessionInfoDto>>> resultDto = new JT808ResultDto<JT808PageResult<List<JT808TcpSessionInfoDto>>>();
            try
            {
                if (pageIndex < 0)
                {
                    pageIndex = 0;
                }
                if (pageSize >= 1000)
                {
                    pageSize = 1000;
                }
                JT808PageResult<List<JT808TcpSessionInfoDto>> pageResult = new JT808PageResult<List<JT808TcpSessionInfoDto>>();
                IEnumerable<JT808TcpSession> sessionInfoDtos = SessionManager.GetTcpByPage();
                pageResult.Data = sessionInfoDtos.Select(s => new JT808TcpSessionInfoDto
                {
                    LastActiveTime = s.ActiveTime,
                    StartTime = s.StartTime,
                    TerminalPhoneNo = s.TerminalPhoneNo,
                    RemoteAddressIP = s.RemoteEndPoint.ToString(),
                }).OrderByDescending(o => o.LastActiveTime).Skip(pageIndex * pageSize).Take(pageSize).ToList();
                pageResult.Total = sessionInfoDtos.Count();
                pageResult.PageIndex = pageIndex;
                pageResult.PageSize = pageSize;
                resultDto.Data = pageResult;
                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Data = new JT808PageResult<List<JT808TcpSessionInfoDto>>();
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 会话服务-通过设备终端号查询对应会话
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost("tcp/session/query-session-by-phoneno")]
        public ActionResult<JT808ResultDto<JT808TcpSessionInfoDto>> QueryTcpSessionByTerminalPhoneNo([FromBody] JT808TerminalPhoneNoDto parameter)
        {
            JT808ResultDto<JT808TcpSessionInfoDto> resultDto = new JT808ResultDto<JT808TcpSessionInfoDto>();
            try
            {
                resultDto.Data = SessionManager.GetTcpAll(w => w.TerminalPhoneNo == parameter.TerminalPhoneNo).Select(s => new JT808TcpSessionInfoDto
                {
                    LastActiveTime = s.ActiveTime,
                    StartTime = s.StartTime,
                    TerminalPhoneNo = s.TerminalPhoneNo,
                    RemoteAddressIP = s.RemoteEndPoint.ToString(),
                }).FirstOrDefault();
                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Data = null;
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 会话服务-通过设备终端号移除对应会话
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost("tcp/session/remove-by-phoneno")]
        public ActionResult<JT808ResultDto<bool>> SessionTcpRemoveByTerminalPhoneNo([FromBody] JT808TerminalPhoneNoDto parameter)
        {
            JT808ResultDto<bool> resultDto = new JT808ResultDto<bool>();
            try
            {
                SessionManager.RemoveByTerminalPhoneNo(parameter.TerminalPhoneNo);
                resultDto.Code = JT808ApiResultCode.Ok;
                resultDto.Data = true;
            }
            catch (Exception ex)
            {
                resultDto.Data = false;
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 会话服务-Udp会话查询
        /// </summary>
        /// <returns></returns>
        [HttpGet("Udp/Session/GetAll")]
        public ActionResult<JT808ResultDto<List<JT808UdpSessionInfoDto>>> SessionUdpGetAll()
        {
            JT808ResultDto<List<JT808UdpSessionInfoDto>> resultDto = new JT808ResultDto<List<JT808UdpSessionInfoDto>>();
            try
            {
                resultDto.Data = SessionManager.GetUdpAll().Select(s => new JT808UdpSessionInfoDto
                {
                    LastActiveTime = s.ActiveTime,
                    StartTime = s.StartTime,
                    TerminalPhoneNo = s.TerminalPhoneNo,
                    RemoteAddressIP = s.RemoteEndPoint.ToString(),
                }).ToList();

                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Data = new List<JT808UdpSessionInfoDto>();
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 会话服务-Udp分页会话查询
        /// jt808api/Udp/Session/SessionUdpByPage?pageIndex=0&pageSize10
        /// </summary>
        /// <returns></returns>
        [HttpGet("Udp/Session/SessionUdpByPage")]
        public ActionResult<JT808ResultDto<JT808PageResult<List<JT808UdpSessionInfoDto>>>> SessionUdpByPage([FromQuery] int pageIndex = 0, [FromQuery] int pageSize = 10)
        {
            JT808ResultDto<JT808PageResult<List<JT808UdpSessionInfoDto>>> resultDto = new JT808ResultDto<JT808PageResult<List<JT808UdpSessionInfoDto>>>();
            try
            {
                if (pageIndex < 0)
                {
                    pageIndex = 0;
                }
                if (pageSize >= 1000)
                {
                    pageSize = 1000;
                }
                JT808PageResult<List<JT808UdpSessionInfoDto>> pageResult = new JT808PageResult<List<JT808UdpSessionInfoDto>>();
                IEnumerable<JT808UdpSession> sessionInfoDtos = SessionManager.GetUdpByPage();
                pageResult.Data = sessionInfoDtos.Select(s => new JT808UdpSessionInfoDto
                {
                    LastActiveTime = s.ActiveTime,
                    StartTime = s.StartTime,
                    TerminalPhoneNo = s.TerminalPhoneNo,
                    RemoteAddressIP = s.RemoteEndPoint.ToString(),
                }).OrderByDescending(o => o.LastActiveTime).Skip(pageIndex * pageSize).Take(pageSize).ToList();
                pageResult.Total = sessionInfoDtos.Count();
                pageResult.PageIndex = pageIndex;
                pageResult.PageSize = pageSize;
                resultDto.Data = pageResult;
                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Data = new JT808PageResult<List<JT808UdpSessionInfoDto>>();
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 会话服务-通过设备终端号查询对应会话
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost("Udp/Session/QuerySessionByTerminalPhoneNo")]
        public ActionResult<JT808ResultDto<JT808UdpSessionInfoDto>> QueryUdpSessionByTerminalPhoneNo([FromBody] JT808TerminalPhoneNoDto parameter)
        {
            JT808ResultDto<JT808UdpSessionInfoDto> resultDto = new JT808ResultDto<JT808UdpSessionInfoDto>();
            try
            {
                resultDto.Data = SessionManager.GetUdpAll(w => w.TerminalPhoneNo == parameter.TerminalPhoneNo).Select(s => new JT808UdpSessionInfoDto
                {
                    LastActiveTime = s.ActiveTime,
                    StartTime = s.StartTime,
                    TerminalPhoneNo = s.TerminalPhoneNo,
                    RemoteAddressIP = s.RemoteEndPoint.ToString(),
                }).FirstOrDefault();
                resultDto.Code = JT808ApiResultCode.Ok;
            }
            catch (Exception ex)
            {
                resultDto.Data = null;
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 会话服务-通过设备终端号移除对应会话
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        [HttpPost("Udp/Session/RemoveByTerminalPhoneNo")]
        public ActionResult<JT808ResultDto<bool>> SessionUdpRemoveByTerminalPhoneNo([FromBody] JT808TerminalPhoneNoDto parameter)
        {
            JT808ResultDto<bool> resultDto = new JT808ResultDto<bool>();
            try
            {
                SessionManager.RemoveByTerminalPhoneNo(parameter.TerminalPhoneNo);
                resultDto.Code = JT808ApiResultCode.Ok;
                resultDto.Data = true;
            }
            catch (Exception ex)
            {
                resultDto.Data = false;
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 黑名单添加
        /// </summary>
        /// <returns></returns>
        [HttpPost("blacklist/add")]
        public ActionResult<JT808ResultDto<bool>> BlacklistAdd([FromBody] JT808TerminalPhoneNoDto parameter)
        {
            JT808ResultDto<bool> resultDto = new JT808ResultDto<bool>();
            try
            {
                BlacklistManager.Add(parameter.TerminalPhoneNo);
                resultDto.Code = JT808ApiResultCode.Ok;
                resultDto.Data = true;
            }
            catch (Exception ex)
            {
                resultDto.Data = false;
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 黑名单删除
        /// </summary>
        /// <returns></returns>
        [HttpPost("blacklist/remove")]
        public ActionResult<JT808ResultDto<bool>> BlacklistRemove([FromBody] JT808TerminalPhoneNoDto parameter)
        {
            JT808ResultDto<bool> resultDto = new JT808ResultDto<bool>();
            try
            {
                BlacklistManager.Remove(parameter.TerminalPhoneNo);
                resultDto.Code = JT808ApiResultCode.Ok;
                resultDto.Data = true;
            }
            catch (Exception ex)
            {
                resultDto.Data = false;
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 黑名单查询
        /// </summary>
        /// <returns></returns>
        [HttpGet("blacklist/get-all")]
        public ActionResult<JT808ResultDto<List<string>>> BlacklistGetAll()
        {
            JT808ResultDto<List<string>> resultDto = new JT808ResultDto<List<string>>();
            try
            {
                resultDto.Code = JT808ApiResultCode.Ok;
                resultDto.Data = BlacklistManager.GetAll();
            }
            catch (Exception ex)
            {
                resultDto.Data = new List<string>();
                resultDto.Code = JT808ApiResultCode.Error;
                resultDto.Message = ex.StackTrace;
            }
            return resultDto;
        }

        /// <summary>
        /// 从 ConcurrentDictionary 中阻塞等待获取指定键的键值对
        /// </summary>
        /// <param name="dictionary">目标字典</param>
        /// <param name="key">要获取的键</param>
        /// <param name="timeoutMilliseconds">超时时间（毫秒）</param>
        /// <returns>是否成功获取到键值对</returns>
        static async Task<(bool Success, byte[] Output)> TryTakeFromDictionaryAsync(ConcurrentDictionary<string, byte[]> dictionary, string key, int timeoutMilliseconds)
        {
            using (var cts = new CancellationTokenSource(timeoutMilliseconds))
            {
                try
                {
                    while (true)
                    {
                        if (dictionary.TryRemove(key, out var output))
                            return (true, output);
                        await Task.Delay(10, cts.Token);
                    }
                }
                catch (OperationCanceledException)
                {
                    return (false, null);
                }
            }
        }
    }
}
